package com.tl.sboot.utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.UUID;

import redis.clients.jedis.Tuple;

/**
 * 得到逆波兰表达式
 * 
 * @author Administrator
 *
 */
public class RPOUtil {
	/**
	 * 获得运算符优先级
	 * 
	 * @param operator
	 * @return
	 */
	public static int getPriority(String operator) {
		final int plusPriority = 2;
		final int multiplyPriority = 3;
		final int minusPriority = 4;
		final int leftBracketPriority = 1;
		if ("+".equals(operator))
			return plusPriority;
		if ("*".equals(operator) || "/".equals(operator))
			return multiplyPriority;
		if ("-".equals(operator))
			return minusPriority;
		if ("(".equals(operator))
			return leftBracketPriority;
		return 0;
	}

	/**
	 * 比较两运算符优先级
	 * 
	 * @param operatorA
	 * @param operatorB
	 * @return
	 */
	public static boolean priorThan(String operatorA, String operatorB) {
		return getPriority(operatorA) > getPriority(operatorB);
	}

	/**
	 * 得到逆波兰表达式
	 * 
	 * @return
	 */
	public static List<String> findRPO(String expression) {
		Map<Integer, String> retrivalWords = new HashMap<Integer, String>();// 检索词表存储区
		Stack<String> operatorList = new Stack<String>();// 算子保留栈
		List<Result> result = new ArrayList<Result>();// 结果保留栈
		expression = expression.concat(",");
		int letterNum = 0;
		for (int i = 0; i < expression.length(); i++) {
			String s = String.valueOf(expression.charAt(i));
			if (s.matches("[\u4e00-\u9fa5 . 、 a-zA-Z]")) {// [\u4e00-\u9fa5]//[a-zA-Z]匹配正则表达式
				letterNum = letterNum + 1;
			} else {
				if (letterNum > 0) {
					String retrivalWord = expression.substring(i - letterNum, i);
					retrivalWords.put(retrivalWords.size() + 1, retrivalWord);
					result.add(new Result(0, retrivalWord));
					letterNum = 0;
				}
				if ("(".equals(s)) {
					operatorList.push("(");
				}
				if ("+*-/".contains(s)) {
					while ((!operatorList.isEmpty()) && (!priorThan(s, operatorList.peek()))) {
						result.add(new Result(1, operatorList.pop()));
					}
					operatorList.push(s);
				}
				if (")".equals(s)) {
					while (!operatorList.peek().equals("(")) {
						result.add(new Result(1, operatorList.pop()));
					}
					operatorList.pop();
				}
				if (",".equals(s)) {
					while (!operatorList.isEmpty()) {
						result.add(new Result(1, operatorList.pop()));
					}
					result.add(new Result(1, ","));
				}
			}
		}
		List<String> newStrResult = new ArrayList<>();
		for (int i = 0; i < result.size(); i++) {
			if (i != result.size() - 1) {
				newStrResult.add(result.get(i).getContent());
			}
		}
		return newStrResult;
	}

	/**
	 * 对逆波兰表达式进行求值
	 */
	public static String operation(String expression, RedisUtil ru) {
		List<String> resluts = findRPO(expression);
		MyStack ms2 = new MyStack();
		for (String s : resluts) {
			if (s.indexOf("SS.") != -1) {
				ms2.push(s);
			} else {
				String lastField = ms2.pop(); // 从后面往前拿数据
				String firstField = ms2.pop();
				lastField = commOperation(s, ru, firstField, lastField);
				ms2.push("" + lastField);
			}
		}
		return ms2.pop();
	}

	/**
	 * 公共运算
	 * 
	 * @param substring
	 * @return
	 */
	public static String commOperation(String operator, RedisUtil ru, String firstField, String lastField) {
		String newFieldName = "UUID." + UUID.randomUUID();
		// String newFieldName = "UUID.StockCode";
		// 计算用户所选数据
		if (operator.equals("+")) {
			ru.zinterstore(newFieldName, null, firstField, lastField);
		} else if (operator.equals("-")) {
			int[] arr = { 1, -1 };
			ru.zinterstore(newFieldName, arr, firstField, lastField);
		} else {
			Set<Tuple> firstSet = ru.zrangeWithScores(firstField, 0, -1);
			Set<Tuple> lastSet = ru.zrangeWithScores(lastField, 0, -1);
			if (operator.equals("*")) {
				for (Tuple tuple1 : firstSet) {
					String stkcode1 = tuple1.getElement();
					double score1 = tuple1.getScore();
					for (Tuple tuple : lastSet) {
						String stkcode = tuple.getElement();
						if (stkcode.equals(stkcode1)) {
							double score = tuple.getScore();
							double value = score1 * score;
							ru.zadd(newFieldName, value, stkcode);
						}
					}
				}
			} else {
				for (Tuple tuple1 : firstSet) {
					String stkcode1 = tuple1.getElement();
					double score1 = tuple1.getScore();
					for (Tuple tuple : lastSet) {
						String stkcode = tuple.getElement();
						if (stkcode.equals(stkcode1)) {
							double score = tuple.getScore();
							double value = score1 / score == 0 ? 1 : score;
							ru.zadd(newFieldName, value, stkcode);
						}
					}
				}
			}
		}
		return newFieldName;
	}
}

/**
 * 逆波兰表达式实体
 * 
 * @author Administrator
 *
 */
class Result {
	private int charactor;
	private String content;

	public Result(int charactor, String content) {
		this.charactor = charactor;
		this.content = content;
	}

	public int getCharactor() {
		return charactor;
	}

	public String getContent() {
		return content;
	}

	public void setCharactor(int charactor) {
		this.charactor = charactor;
	}

	public void setContent(String content) {
		this.content = content;
	}
}

class MyStack {
	private List<String> l;
	private int size;
	public String top;

	public MyStack() {
		l = new ArrayList<String>();
		size = 0;
		top = null;
	}

	public int size() {
		return size;
	}

	public void push(String s) {
		l.add(s);
		top = s;
		size++;
	}

	public String pop() {
		String s = l.get(size - 1);
		l.remove(size - 1);
		size--;
		top = size == 0 ? null : l.get(size - 1);
		return s;
	}
}
